#include "htimer.h"
#include "AAMConsole.h"
#include "VO_AAMBasic.h"
#include <fstream>
#include <stdlib.h>
#include <vector>
#include <sstream>
#include <iostream>
#include <string>
#include <cstdlib>
#include <cmath>

#include <boost/regex/v4/fileiter.hpp>

#include "cv.h"
#include "highgui.h"
#include "ml.h"

#include "VO_Common.h"
#include "VO_IO.h"

#include "utils.h"

using namespace std;

// configuration of which model and builder classes to use
// (not very elegant.... I know)
#ifndef C_AAMMODEL
#define C_AAMMODEL CAAMModel
#endif
#ifndef C_AAMBUILDER
#define C_AAMBUILDER CAAMBuilder
#endif


/**

	 @author   Salil Deena
	 @version  4-13-2009

	 @memo     
	 @doc      
	 @see      

	 @param    
	 @param    

	 @return   

	 */ 
CAAMConsole::CAAMConsole(int argc, char **argv) {

	// store command line
	m_argv = argv;
	m_argc = argc;

	// setup vissdk
	//VisPGlobals()->SetDoesBMPFileWidthIncludePadding(false);


	// insert the implemented modes
	// not very robust but ok
	// as long as this method is ended
	// with a exit(0) :-)
	CAAMConsoleModeB b( m_argv[0] );
	m_Modes.push_back( &b );	
	CAAMConsoleModeC2S c2s( m_argv[0] );
	m_Modes.push_back( &c2s );	
	CAAMConsoleModeE e( m_argv[0] );
	m_Modes.push_back( &e );
	CAAMConsoleModeER er( m_argv[0] );
	m_Modes.push_back( &er );
	CAAMConsoleModeEval eval( m_argv[0] );
	m_Modes.push_back( &eval );
	CAAMConsoleModeS s( m_argv[0] );
	m_Modes.push_back( &s );
	CAAMConsoleModeSS ss( m_argv[0] );
	m_Modes.push_back( &ss );
	CAAMConsoleModeW w( m_argv[0] );
	m_Modes.push_back( &w );
	CAAMConsoleModeG g( m_argv[0] );
	m_Modes.push_back( &g );
	CAAMConsoleModeG2 g2( m_argv[0] );
	m_Modes.push_back( &g2 );			   
	CAAMConsoleModeGP gp( m_argv[0] );
	m_Modes.push_back( &gp );
	CAAMConsoleModeT t( m_argv[0] );
	m_Modes.push_back( &t ); 
	CAAMConsoleModeREG reg( m_argv[0] );
	m_Modes.push_back( &reg );		   

	// parse command line
	if ( argc<2 ) {

		// we need at least two arguments to do something
		PrintUsage();
		exit(1);
	}

	// print help if requested
	if ( IsHelpSwitch( argv[1]) ) {

		PrintHelp();
		exit(0);
	}

	if ( string(argv[1]) =="-full"	) {

		// print full help
		PrintFullHelp();
		exit(0);
	}

	int modeID = IsModeAllowed( argv[1] );

	if ( modeID==-1 ) {

		// the specified mode was not allowed
		PrintUsage();
		exit(1);
	}

	// main call
	string pnuc(m_argv[0]);
	//pnuc.MakeUpper();
	try {

		// remove the mode info from the command line
		// and run the mode
		m_Modes[modeID]->Main( argc-2, &(argv[2]) );
	} 
	catch(...) {

		printf("%s: Unknown exception thrown. Exiting.\n", pnuc.c_str() );

		// #ifdef _DEBUG
		throw; // rethrow exception
		// #else
		exit(-1);
		// #endif      

	}

	// the mode was handled successfully if we reach this point
	exit(0);
}



/**

 @author   Salil Deena
 @version  4-25-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
bool CAAMConsole::IsHelpSwitch( const string &arg ) {

	return  arg =="-help"	||
		arg =="--h"	||
		arg =="-h"	||
		arg =="-?"	||
		arg =="?";
}


/**

 @author   Salil Deena
 @version  4-13-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
void CAAMConsole::PrintHelp() const {

	fprintf( stdout, "The tool '%s' is the console interface to the AAM-API.\n", m_argv[0] );
}



/**

 @author   Salil Deena
 @version  4-19-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
void CAAMConsole::PrintFullHelp() const {

	PrintUsage();
	PrintHelp();

	for(unsigned int i=0;i<m_Modes.size();i++) {

		// for each mode
		fprintf( stdout, "\n---------------------------------------------------------------------\n" );
		fprintf( stdout, "MODE: %s - %s\n",

		m_Modes[i]->Name().c_str(),
		m_Modes[i]->Desc().c_str()	);
		fprintf( stdout, "---------------------------------------------------------------------\n\n" );
		m_Modes[i]->PrintUsage();
	}    
}


/**

 @author   Salil Deena
 @version  4-13-2009

 @memo     Checks if the given mode is allowed.
 @doc      
 @see      

 @param    
 @param    

 @return   The mode id.

 */
int CAAMConsole::IsModeAllowed( const string &modeStr ) const {


	for(unsigned int i=0;i<m_Modes.size();i++) {

		if ( modeStr==m_Modes[i]->Name() ) {

			// the mode was found
			return i;
		}
	}

	// we never found the mode
	return -1;
}



/**

 @author   Salil Deena
 @version  4-13-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
void CAAMConsole::PrintUsage() const {

	string pnuc(m_argv[0]);
	//pnuc.MakeUpper();
	fprintf( stdout, "%s - Active Appearance Model Console Interface - version 1.00\n", pnuc.c_str() );
	fprintf( stdout, "Copyright (c) Salil Deena 2009, deenas@cs.man.ac.uk. All rights reserved.\n" );
	fprintf( stdout, "This version of %s was built on: %s %s\n\n", pnuc.c_str(), __DATE__, __TIME__ );
	fprintf( stdout, "USAGE:\n" );
	fprintf( stdout, "       %s <", m_argv[0] );
	for(unsigned int i=0;i<m_Modes.size();i++) 
		fprintf( stdout, "%s%s", i ? "|":"", m_Modes[i]->Name().c_str() );
	fprintf( stdout, "> [additional mode arguments]\n\n" );

	fprintf( stdout, "MODES:\n");
	for(unsigned int i=0;i<m_Modes.size();i++) {

		fprintf( stdout, "       %s %s %s\n", m_argv[0], m_Modes[i]->Name().c_str(), m_Modes[i]->Usage().c_str() );
	}

	fprintf( stdout, "\nFor futher help write: '%s -help', '%s -full' or '%s <modename> -help'\n\n", 
	m_argv[0], m_argv[0], m_argv[0] );
}



/**

 @author   Salil Deena
 @version  4-13-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
void CAAMConsoleMode::PrintUsage() const {

	fprintf(stdout, "USAGE:\n      %s %s %s\n\n", m_ProgName.c_str(), m_Name.c_str(), m_Usage.c_str() );
	fprintf(stdout, "DESCRIPTION:\n\n%s\n\n%s\n", m_Desc.c_str(), m_LongDesc.c_str() );
}


/**

 @author   Salil Deena
 @version  4-13-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
int CAAMConsoleMode::Main(int argc, char **argv) const {

	// check for help param
	if (argc==1) {

		if ( CAAMConsole::IsHelpSwitch( argv[0] ) ) {

			PrintUsage();
			exit(0);
		}
	}

	// check param amount
	if ( !(argc>=m_NMinParam && argc<=m_NMaxParam) ) {

		PrintUsage();
		exit(1);
	}

	return 0;
}


/**

 @author   Salil Deena
 @version  4-14-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
CAAMConsoleModeW::CAAMConsoleModeW( const string &progname ) {


	m_ProgName  = progname;
	m_NMinParam = 2;
	m_NMaxParam = 3;


	m_Name		= "w";
	m_Usage		= "<write options> <annotation> [reduction factor]";
	m_Desc		= string("Plots an annotation into it's host image.\n\n")+
		string("<write options>    Set one or several of the following options to get\n")+
		string("                   the desired result (not sensitive to ordering):\n\n")+
		string("                     s   Plots the shape as connecting lines\n")+
		string("                     p   Plots all shape points as cross-hairs\n")+
		string("                     i   Dots the interior of the shape\n")+
		string("                     n   Draws point normals\n")+
		string("                     m   Plots a Delaunay triangulation of the shape\n")+
		string("                     t   Similar to 'm' but removes concave triangles and holes\n\n")+                  
		string("<annotation>       An .asf-file.\n\n")+
		string("[reduction factor] Optional integer image/annotation reduction factor [2-n]\n\n")+
		string("Example usage:\n\n       ") + m_ProgName + string(" w si c6302.asf\n" );		          
	m_LongDesc	= "";
}


/**

 @author   Salil Deena
 @version  4-14-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
int CAAMConsoleModeW::Main(int argc, char **argv) const {		

	return 0;
}	



/**

 @author   Salil Deena
 @version  4-14-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
CAAMConsoleModeB::CAAMConsoleModeB( const string &progname ) {

	m_ProgName  = progname;
	m_NMinParam = 2;
	m_NMaxParam = 2;

	m_Name		= "b";
	m_Usage		= "<model dir> <acf file>";
	m_Desc		= "Builds an Active Appearance Model.";
	m_LongDesc	= string("In this mode the principal component analysis, parameter optimization training\n")+
		string("etc. are done.\n\n" )+	  
		string("model dir : The path to the AAM model data files.\n")+
		string("acf file  : AAM configuration file.\n");				  
}


/**

 @author   Salil Deena
 @version  9-21-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
int CAAMConsoleModeB::Main(int argc, char **argv) const {	
	// call base implementation
	CAAMConsoleMode::Main( argc, argv );

	string model_dir = argv[0];
	string act_file = argv[1];

	string prePath;
	float shape_var;
	float texture_var;
	float combined_var;
	bool mode;

	parseActFile (act_file, prePath, shape_var, texture_var, combined_var, mode);

	if (!boost::filesystem::is_directory(prePath) )
	{
		cout << "The path for training data specified in the conf file is invalid." << endl;
		exit(1);
	}	

	// specify the number of channels of the dataset
	int nChan;	

	if (mode == 0)
		nChan = GRAYCHANNELS;
	else if (mode == 1)
		nChan = COLORCHANNELS;

	// specify the method to be applied
	int med 	= AAM_BASIC;		                	// AAM_BASIC, AAM_CMUINVERSECOMPOSITIONAL

	// specify the texture extraction method
	int tmd     	= DIRECTTEXTURE;			        // DIRECTTEXTURE, LAPLACETEXTURE, HARRISCORNERTEXTURE, HISTOGRAMEQUALIZED, GABOR, SEGMENTATION

	string                  hostImagePath, hostAnnotatedPath, trainedDataPath;
	string                  strWidth, strHeight, strNumOfSamples;
	stringstream            ssWidth, ssHeight, ssNumOfSamples;
	vector<string>          AllAnnotatedFiles, AllImgFiles4Training;
	vector<IplImage*>       imgs;
	vector<VO_AAMShape2D>   shps;

	hostImagePath 		= prePath + "/images/";
	hostAnnotatedPath 	= prePath + "/annotations/";

	//char current_directory[200];
	//GetCurrentPath(current_directory);

	if (!boost::filesystem::is_directory(model_dir) )
	{
		cout << "The directory specified does not exist" << endl;
		exit(1);
	}

	// 2. Load all images
	AllImgFiles4Training 	= VO_IO::ScanNSortImagesInDirectory ( hostImagePath );
	// 3. Load the annotated information
	AllAnnotatedFiles	= VO_IO::ScanNSortAnnotationInDirectory ( hostAnnotatedPath );

	if (AllImgFiles4Training.size() == 0)
	{
		cout << "No images in " << hostImagePath << "...exiting" << endl;
		exit(1);
	}

	if (AllAnnotatedFiles.size() == 0)
	{
		cout << "No annotations in " << hostImagePath << "...exiting" << endl;
		exit(1);
	}

	if (AllImgFiles4Training.size()  != AllAnnotatedFiles.size())
	{
		cout << "The number of images and annotation are different...exiting" << endl;
		exit(1);
	}

	switch ( nChan )
	{
		case GRAYCHANNELS:
		{
			for ( unsigned int i=0; i < AllImgFiles4Training.size(); i++ )
			{
				imgs.push_back ( cvLoadImage ( AllImgFiles4Training[i].c_str (), CV_LOAD_IMAGE_GRAYSCALE ) );
			}

			ssWidth << imgs[0]->width;
			ssWidth >> strWidth;
			ssHeight << imgs[0]->height;
			ssHeight >> strHeight;
			ssNumOfSamples << AllImgFiles4Training.size();
			ssNumOfSamples >> strNumOfSamples;
			//trainedDataPath = string(current_directory) + "/traineddata";
			trainedDataPath = model_dir + "/traineddata";

			if (!boost::filesystem::is_directory(trainedDataPath) )
				boost::filesystem::create_directory( trainedDataPath );

			trainedDataPath = trainedDataPath + "/Gray";

			if (!boost::filesystem::is_directory(trainedDataPath) )
				boost::filesystem::create_directory( trainedDataPath );
		}
			break;

		case COLORCHANNELS:
		{
			for ( unsigned int i=0; i < AllImgFiles4Training.size(); i++ )
			{
				cout << "Reading image " << AllImgFiles4Training[i] << endl;				
				imgs.push_back ( cvLoadImage ( AllImgFiles4Training[i].c_str (), CV_LOAD_IMAGE_COLOR ) );
			}
			ssWidth << imgs[0]->width;
			ssWidth >> strWidth;
			ssHeight << imgs[0]->height;
			ssHeight >> strHeight;
			ssNumOfSamples << AllImgFiles4Training.size();
			ssNumOfSamples >> strNumOfSamples;
			//trainedDataPath = string(current_directory) + "/traineddata";
			trainedDataPath = model_dir + "/traineddata";

			if (!boost::filesystem::is_directory(trainedDataPath) )
				boost::filesystem::create_directory( trainedDataPath );

			trainedDataPath = trainedDataPath + "/RGB";

			if (!boost::filesystem::is_directory(trainedDataPath) )
				boost::filesystem::create_directory( trainedDataPath );

		}
			break;
	}

	// Read all ASF file data into shps and scale back to the original size
	VO_AAMPoint2D tempPoint;
	CvPoint2D32f tempPoint2D;			
	for ( unsigned int i=0; i < AllAnnotatedFiles.size(); i++ )
	{
		cout << "Reading shape " << AllAnnotatedFiles[i] << endl;		
		VO_AAMShape2D tempAAMShape;
		VO_AAMShape2D::ReadASF ( AllAnnotatedFiles[i], tempAAMShape );
		tempAAMShape.ScaleXY ( ( float ) imgs[i]->width, ( float ) imgs[i]->height );
		tempPoint = tempAAMShape.GetPoint(0);
		tempPoint2D = tempPoint.GetXY();
		shps.push_back ( tempAAMShape );
	}

	// We could train the components respectively here.
	switch (med)
	{
		case AAM_BASIC:
		{
			VO_AAMBasic testAAMBasic;
			//cout << "So far so good AAM" << endl;
			testAAMBasic.VO_BuildAAMBasic ( shps, imgs, nChan, tmd, shape_var, texture_var, combined_var );

			cout << "Built successfully" << endl; 	
			testAAMBasic.VO_Save(trainedDataPath);
		}
			break;
		case AAM_CMUINVERSECOMPOSITIONAL:
		{
			//VO_AAMICIA testAAMICIA;
			//testAAMICIA.VO_BuildAAMICIA ( shps, imgs, nChan, tmd, 0.95f, 0.95f );
			//testAAMICIA.VO_Save(trainedDataPath);
		}
		default:
			break;
	}

	return EXIT_SUCCESS;	
}

/**

 @author   Salil Deena
 @version  20-4-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
CAAMConsoleModeC2S::CAAMConsoleModeC2S( const string &progname ) {

	m_ProgName  = progname;
	m_NMinParam = 3;
	m_NMaxParam = 3;

	m_Name		= "c2s";
	m_Usage		= "<model dir> <data file> <sample image>";
	m_Desc		= "Converts AAM parameters to Active Shape parameters.";
	m_LongDesc	= string("In this mode the AAM parameters, read from the file data_file.txt in the current directory are\n")+
		string("projected back to the data space and used to obtain the Active Shape parameters.\n\n" )+
		string("model dir : Path to the AAM model data files. \n")+
		string("data file : The file containing the AAM parameters .\n")+
		string("sample image : A sample image from which the model has been built. \n");			  	  
}

/**

 @author   Salil Deena
 @version  4-20-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
int CAAMConsoleModeC2S::Main(int argc, char **argv) const {

	// we're done
	return 0;
}


/**

 @author   Salil Deena
 @version  4-14-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
CAAMConsoleModeE::CAAMConsoleModeE( const string &progname ) {

	m_ProgName  = progname;
	m_NMinParam = 2;
	m_NMaxParam = 4;

	m_Name		= "e";
	m_Usage		= "<model dir> <dir> [still|movie|both|none*] [pseudo|auto*]";
	m_Desc		= "Evaluates an Active Appearance Model.";
	m_LongDesc	= string("model dir              : The path to the AAM model data files.\n")+
		string("dir                : Directory containing images and ground truth annotations.\n")+				  
		string("[still|movie|both] : Write stills of the initial and optimized model\n")+
		string("                     and/or movies of the complete optimization.\n")+
		string("[pseudo|auto*]     : Initialisation method.\n")+				  
		string("\nOutput is written in the input dir in the file 'results.txt'\n")+
		string("Default settings are marked with an asterisk (*)\n");
}

/**

 @author   Salil Deena
 @version  4-17-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
int CAAMConsoleModeE::Main(int argc, char **argv) const {

	// we're done
	return 0;
}

/**

 @author   Salil Deena
 @version  June 2008

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
CAAMConsoleModeER::CAAMConsoleModeER( const string &progname ) {

	m_ProgName  = progname;
	m_NMinParam = 2;
	m_NMaxParam = 4;

	m_Name		= "er";
	m_Usage		= "<model dir> <dir> <data file> <error norm>";
	m_Desc		= "Evaluates Reconstruction Error from Active Appearance Model parameters.";
	m_LongDesc	= string("model dir             : The path to the AAM model data files.\n")+
		string("dir                : Directory containing images and ground truth annotations.\n")+				  
		string("datafile           : The name of the data file containing the AAM parameters.\n")+	
		string("error norm         : A value between 0 and 7. 0:L2 norm, 1: Mahal dist, 2:Lorentzian norm, 3:Abs autocorrelation, 4:Mutual information, 5:RMS, 6:L1 norm, 7:Linfty norm.\n")+	
		string("Default settings are marked with an asterisk (*)\n");
}

/**

 @author   Salil Deena
 @version  6-30-2008

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
int CAAMConsoleModeER::Main(int argc, char **argv) const {

	// we're done
	return 0;
}

/**

 @author   Salil Deena
 @version  November 2008

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
CAAMConsoleModeEval::CAAMConsoleModeEval( const string &progname ) {

	m_ProgName  = progname;
	m_NMinParam = 4;
	m_NMaxParam = 4;

	m_Name		= "eval";
	m_Usage		= "<model dir> <dir> <error norm> <shape|texture>";
	m_Desc		= "Evaluates Reconstruction from AAM parameters from test data, when compared against ground truth.";
	m_LongDesc	= string("model dir              : The path to the AAM model data files.\n")+
		string("dir                : Directory containing directories who name start with 'seq'. These should contain a file called 'ground_truth.txt' and another one called 'test_results.txt'\n")+				  
		string("error norm         : A value between 0 and 7. 0:L2 norm, 1: Mahal dist, 2:Lorentzian norm, 3:Abs autocorrelation, 4:Mutual information, 5:RMS, 6:L1 norm, 7:Linfty norm.\n")+	
		string("<shape|texture>    : Computes errors either in terms of shape or texture.\n")+	
		string("Default settings are marked with an asterisk (*)\n");
}

/**

 @author   Salil Deena
 @version  11-10-2008

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
int CAAMConsoleModeEval::Main(int argc, char **argv) const {

	// we're done
	return 0;
}

/**

 @author   Salil Deena
 @version  6-8-2008

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
CAAMConsoleModeGP::CAAMConsoleModeGP( const string &progname ) {

	m_ProgName  = progname;
	m_NMinParam = 2;
	m_NMaxParam = 4;

	m_Name		= "gp";
	m_Usage		= "<model dir> <dir>";
	m_Desc		= "Generates Active Appearance Model parameters from images and annotations.";
	m_LongDesc	= string("model dir              : The path to the AAM model data files.\n")+
		string("dir                : Directory containing images and ground truth annotations.\n");
}


/**

 @author   Salil Deena
 @version  6-8-2008

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
int CAAMConsoleModeGP::Main(int argc, char **argv) const {
	// call base implementation
	CAAMConsoleMode::Main( argc, argv );

	// setup input parameters	
	string model_dir	= argv[0];		
	string input_dir	= argv[1];
	string test_model_dir;	
	int nChan;
	int num_samples;
	CvMat *AAMParams, *ConcatenatedParams, *shapeAlignmentParams;

	test_model_dir = model_dir + "/traineddata/RGB/";	

	if (boost::filesystem::is_directory(test_model_dir) )
	{
		nChan = COLORCHANNELS;	
	}
	else
	{
		test_model_dir = model_dir + "/traineddata/Gray/";

		if (boost::filesystem::is_directory(test_model_dir) )
		{
			nChan = GRAYCHANNELS;		
		}
		else
		{
			cout << "No AAM model data files are found in the specified directory" << endl;
			exit(1);
		}	
	}

	// specify the texture extraction method
	int tmd     	= DIRECTTEXTURE;			        // DIRECTTEXTURE, LAPLACETEXTURE, HARRISCORNERTEXTURE, HISTOGRAMEQUALIZED, GABOR, SEGMENTATION

	string                  hostImagePath, hostAnnotatedPath, trainedDataPath;
	string                  strWidth, strHeight, strNumOfSamples;
	stringstream            ssWidth, ssHeight, ssNumOfSamples;
	vector<string>          AllAnnotatedFiles, AllImgFiles;
	vector<IplImage*>       imgs;
	vector<VO_AAMShape2D>   shps;

	if (!boost::filesystem::is_directory(model_dir) )
	{
		cout << "The directory specified for the AAM model is invalid" << endl;
		exit(1);
	}

	if (!boost::filesystem::is_directory(input_dir) )
	{
		cout << "The directory specified for reading the images and annotations is invalid" << endl;
		exit(1);
	}

	VO_AAMBasic aam_model;
	aam_model.VO_Load (test_model_dir);	

	hostImagePath 		= input_dir;
	hostAnnotatedPath 	= input_dir;

	// 2. Load all images
	AllImgFiles 	= VO_IO::ScanNSortImagesInDirectory ( hostImagePath );
	// 3. Load the annotated information
	AllAnnotatedFiles	= VO_IO::ScanNSortAnnotationInDirectory ( hostAnnotatedPath );

	if (AllImgFiles.size() == 0)
	{
		cout << "No images in " << hostImagePath << "...exiting" << endl;
		exit(1);
	}

	if (AllAnnotatedFiles.size() == 0)
	{
		cout << "No annotations in " << hostImagePath << "...exiting" << endl;
		exit(1);
	}

	if (AllImgFiles.size()  != AllAnnotatedFiles.size())
	{
		cout << "The number of images and annotation are different...exiting" << endl;
		exit(1);
	}

	switch ( nChan )
	{
		case GRAYCHANNELS:
		{
			for ( unsigned int i=0; i < AllImgFiles.size(); i++ )
			{
				imgs.push_back ( cvLoadImage ( AllImgFiles[i].c_str (), CV_LOAD_IMAGE_GRAYSCALE ) );
			}

			ssWidth << imgs[0]->width;
			ssWidth >> strWidth;
			ssHeight << imgs[0]->height;
			ssHeight >> strHeight;
			ssNumOfSamples << AllImgFiles.size();
			ssNumOfSamples >> strNumOfSamples;
		}
			break;

		case COLORCHANNELS:
		{
			for ( unsigned int i=0; i < AllImgFiles.size(); i++ )
			{
				cout << "Reading image " << AllImgFiles[i] << endl;				
				imgs.push_back ( cvLoadImage ( AllImgFiles[i].c_str (), CV_LOAD_IMAGE_COLOR ) );
			}
			ssWidth << imgs[0]->width;
			ssWidth >> strWidth;
			ssHeight << imgs[0]->height;
			ssHeight >> strHeight;
			ssNumOfSamples << AllImgFiles.size();
			ssNumOfSamples >> strNumOfSamples;
		}
			break;
	}

	// Read all ASF file data into shps and scale back to the original size
	VO_AAMPoint2D tempPoint;
	CvPoint2D32f tempPoint2D;			
	for ( unsigned int i=0; i < AllAnnotatedFiles.size(); i++ )
	{
		cout << "Reading shape " << AllAnnotatedFiles[i] << endl;		
		VO_AAMShape2D tempAAMShape;
		VO_AAMShape2D::ReadASF ( AllAnnotatedFiles[i], tempAAMShape );
		tempAAMShape.ScaleXY ( ( float ) imgs[i]->width, ( float ) imgs[i]->height );
		tempPoint = tempAAMShape.GetPoint(0);
		tempPoint2D = tempPoint.GetXY();
		shps.push_back ( tempAAMShape );
	}

	num_samples = AllImgFiles.size();

	ConcatenatedParams = cvCreateMat(num_samples, aam_model.GetNbOfConcatenated(), CV_32FC1);
	AAMParams = cvCreateMat(num_samples, aam_model.GetNbOfTruncatedConcatenated(), CV_32FC1);
	shapeAlignmentParams = cvCreateMat(num_samples, 4, CV_32FC1);
	//ConcatenatedParams = cvCreateMat(num_samples, aam_model.GetNbOfTruncatedConcatenated(), CV_32FC1);
	aam_model.VO_ExtractAAMParams (shps, imgs, AAMParams, ConcatenatedParams, shapeAlignmentParams, num_samples);

	cout << endl << "Writing data files ..." << endl;
	string tempfn;
	fstream fp;
	char image_num[100];

	string dataFilePath = input_dir + "/" + "__eval__";
	// Write the AAM params to a text file
	if (!boost::filesystem::is_directory(dataFilePath) )
		boost::filesystem::create_directory( dataFilePath );

	// Write the AAM params
	tempfn = dataFilePath + "/aam_params" + ".txt";
	fp.open(tempfn.c_str (), ios::out);

	for (unsigned int i = 0; i < AAMParams->rows; i++)
	{
		sprintf(image_num, "%.04d", i + 1);
		fp << "Recon-" << image_num << endl;
		fp << aam_model.GetNbOfTruncatedConcatenated() << " ";
		for (unsigned int j = 0; j < AAMParams->cols; j++)
		{
			fp << CV_MAT_ELEM( *AAMParams, float, i, j) << " " ;
		}
		fp << endl;
	}
	fp.close();

	// Write the concatenated params
	tempfn = dataFilePath + "/concatenated_params" + ".txt";
	fp.open(tempfn.c_str (), ios::out);

	for (unsigned int i = 0; i < ConcatenatedParams->rows; i++)
	{
		sprintf(image_num, "%.04d", i + 1);
		fp << "Recon-" << image_num << endl;
		fp << aam_model.GetNbOfConcatenated() << " ";
		for (unsigned int j = 0; j < ConcatenatedParams->cols; j++)
		{
			fp << CV_MAT_ELEM( *ConcatenatedParams, float, i, j) << " " ;
		}
		fp << endl;
	}
	fp.close();

	// Write the shape alignment params
	tempfn = dataFilePath + "/asm_alignment_params" + ".txt";
	fp.open(tempfn.c_str (), ios::out);

	for (unsigned int i = 0; i < shapeAlignmentParams->rows; i++)
	{
		sprintf(image_num, "%.04d", i + 1);
		fp << "Recon-" << image_num << endl;
		for (unsigned int j = 0; j < shapeAlignmentParams->cols; j++)
		{
			fp << CV_MAT_ELEM( *shapeAlignmentParams, float, i, j) << " " ;
		}
		fp << endl;
	}
	fp.close();

	cvReleaseMat( &AAMParams);
	cvReleaseMat( &ConcatenatedParams);
	cvReleaseMat( &shapeAlignmentParams);

	// we're done
	return 0;
}


/**

 @author   Salil Deena
 @version  4-17-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
CAAMConsoleModeS::CAAMConsoleModeS( const string &progname ) {

	m_ProgName  = progname;
	m_NMinParam = 2;
	m_NMaxParam = 3;

	m_Name		= "s";
	m_Usage		= "<model dir> <input dir> [movie filename]";
	m_Desc		= "Active Appearance Model search.";
	m_LongDesc	= "Search output is written in the input dir.\nAutomatic initialisation is performed on all BMP images.\n";
}



/**

 @author   Salil Deena
 @version  4-17-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
int CAAMConsoleModeS::Main(int argc, char **argv) const {
	// call base implementation
	CAAMConsoleMode::Main( argc, argv );

	// setup input parameters	
	string model_dir	= argv[0];		
	string input_dir	= argv[1];
	string test_model_dir;	
	int nChan;
	int num_samples;

	test_model_dir = model_dir + "/traineddata/RGB/";	

	if (boost::filesystem::is_directory(test_model_dir) )
	{
		nChan = COLORCHANNELS;	
	}
	else
	{
		test_model_dir = model_dir + "/traineddata/Gray/";

		if (boost::filesystem::is_directory(test_model_dir) )
		{
			nChan = GRAYCHANNELS;		
		}
		else
		{
			cout << "No AAM model data files are found in the specified directory" << endl;
			exit(1);
		}	
	}

	// specify the texture extraction method
	int tmd     	= DIRECTTEXTURE;			        // DIRECTTEXTURE, LAPLACETEXTURE, HARRISCORNERTEXTURE, HISTOGRAMEQUALIZED, GABOR, SEGMENTATION

	string                  hostImagePath, hostAnnotatedPath, trainedDataPath;
	stringstream            ssWidth, ssHeight, ssNumOfSamples;
	vector<string>          AllAnnotatedFiles, AllImgFiles;
	VO_AAMShape2D s;
	VO_AAMShape2D temp_shape;
	IplImage*     img;
	IplImage*     outImg;
	CvMat* c;

	if (!boost::filesystem::is_directory(model_dir) )
	{
		cout << "The directory specified for the AAM model is invalid" << endl;
		exit(1);
	}

	if (!boost::filesystem::is_directory(input_dir) )
	{
		cout << "The directory specified for reading the images and annotations is invalid" << endl;
		exit(1);
	}

	VO_AAMBasic aam_model;
	aam_model.VO_Load (test_model_dir);	

	c = cvCreateMat(1, aam_model.GetNbOfTruncatedConcatenated(), CV_32FC1);

	hostImagePath 		= input_dir;

	// 2. Load all images
	AllImgFiles 	= VO_IO::ScanNSortImagesInDirectory ( hostImagePath );

	if (AllImgFiles.size() == 0)
	{
		cout << "No images in the current directory...exiting" << endl;
		exit(1);
	}

	// Track each file in the directory
	vector<string> image_filename_tokens;
	vector<string> last_image_filename_tokens;

	for (int i = 0; i < AllImgFiles.size(); i++)
	{
		cout << "Reading image " << AllImgFiles[i] << endl;				
		switch ( nChan )
		{
			case GRAYCHANNELS:
			{
				img = cvLoadImage ( AllImgFiles[i].c_str (), CV_LOAD_IMAGE_GRAYSCALE );
			}
			break;

			case COLORCHANNELS:
			{
				img = cvLoadImage ( AllImgFiles[i].c_str (), CV_LOAD_IMAGE_COLOR ) ;
			}
			break;
		}

		ssWidth << img->width;
		ssHeight << img->height;
		ssNumOfSamples << AllImgFiles.size();

		string orig_image_file = AllImgFiles[i].c_str ();
		image_filename_tokens.clear();
		last_image_filename_tokens.clear();
		TokenizeIntoTokensOnly(orig_image_file, image_filename_tokens, ".");
		TokenizeIntoTokensOnly(image_filename_tokens[image_filename_tokens.size()-2], last_image_filename_tokens, "/");

		string asf_file = last_image_filename_tokens[last_image_filename_tokens.size()-1] + ".asf";
		string image_file_opt_output = last_image_filename_tokens[last_image_filename_tokens.size()-1] + "_opt." + image_filename_tokens[image_filename_tokens.size()-1];
		string image_file_init_output = last_image_filename_tokens[last_image_filename_tokens.size()-1] + "_init." + image_filename_tokens[image_filename_tokens.size()-1];
		string image_file_input = last_image_filename_tokens[last_image_filename_tokens.size()-1] + "." + image_filename_tokens[image_filename_tokens.size()-1];

		cout << "Tracking image " << image_file_input << endl; 	

		string target_asf_file = input_dir + "/" + asf_file;
		string target_image_init_file = input_dir + "/" + image_file_init_output;
		string target_image_opt_file = input_dir + "/" + image_file_opt_output;

		// Obtain reference shape
		s = aam_model.GetAAMMeanShape();
		s.CopyShapeParams (aam_model.GetAAMShapes()[0]);

		cvZero(c);

		cout << "Initialising search on " << image_file_input << endl;
		aam_model.InitializeSearch (img, s, c);

		outImg = cvCloneImage (img);
		aam_model.VO_PutShapeOnTemplateFace(s, img, outImg);
		cvSaveImage( target_image_init_file.c_str(), outImg);

		// Perform the search
		cout << "Optimising search on " << image_file_input << endl;
		aam_model.OptimizeModel(img, s, c, 30 );

		outImg = cvCloneImage (img);
		aam_model.VO_PutShapeOnTemplateFace(s, img, outImg);
		cvSaveImage( target_image_opt_file.c_str(), outImg);

		s.WriteASF(target_asf_file, image_file_input, img->width, img->height);		
	}

	cvReleaseMat( &c);
	cvReleaseImage( &img);
	cvReleaseImage ( &outImg );

	// we're done
	return 0;
}


/**

 @author   Salil DEENA
 @version  10-09-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
CAAMConsoleModeSS::CAAMConsoleModeSS( const string &progname ) {

	m_ProgName  = progname;
	m_NMinParam = 2;
	m_NMaxParam = 2;

	m_Name		= "ss";
	m_Usage		= "<model dir> <input dir> ";
	m_Desc		= "Active Appearance Model search of a sequence of images";
	m_LongDesc	= "Search output is written in the input dir.\n Initialisation is done from the previous frame.\n";
}



/**

 @author   Salil Deena
 @version  6-22-2004

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
int CAAMConsoleModeSS::Main(int argc, char **argv) const {
	// call base implementation
	CAAMConsoleMode::Main( argc, argv );

	// setup input parameters	
	string model_dir	= argv[0];		
	string input_dir	= argv[1];
	string test_model_dir;	
	int nChan;
	int num_samples;

	test_model_dir = model_dir + "/traineddata/RGB/";	

	if (boost::filesystem::is_directory(test_model_dir) )
	{
		nChan = COLORCHANNELS;	
	}
	else
	{
		test_model_dir = model_dir + "/traineddata/Gray/";

		if (boost::filesystem::is_directory(test_model_dir) )
		{
			nChan = GRAYCHANNELS;		
		}
		else
		{
			cout << "No AAM model data files are found in the specified directory" << endl;
			exit(1);
		}	
	}

	// specify the texture extraction method
	int tmd     	= DIRECTTEXTURE;			        // DIRECTTEXTURE, LAPLACETEXTURE, HARRISCORNERTEXTURE, HISTOGRAMEQUALIZED, GABOR, SEGMENTATION

	string                  hostImagePath, hostAnnotatedPath, trainedDataPath;
	string                  strWidth, strHeight, strNumOfSamples;
	stringstream            ssWidth, ssHeight, ssNumOfSamples;
	vector<string>          AllAnnotatedFiles, AllImgFiles;
	vector<IplImage*>       imgs;
	VO_AAMShape2D s;
	VO_AAMShape2D temp_shape;

	if (!boost::filesystem::is_directory(model_dir) )
	{
		cout << "The directory specified for the AAM model is invalid" << endl;
		exit(1);
	}

	if (!boost::filesystem::is_directory(input_dir) )
	{
		cout << "The directory specified for reading the images and annotations is invalid" << endl;
		exit(1);
	}

	VO_AAMBasic aam_model;
	aam_model.VO_Load (test_model_dir);	

	hostImagePath 		= input_dir;

	// 2. Load all images
	AllImgFiles 	= VO_IO::ScanNSortImagesInDirectory ( hostImagePath );

	if (AllImgFiles.size() == 0)
	{
		cout << "No images in the current directory...exiting" << endl;
		exit(1);
	}

	switch ( nChan )
	{
		case GRAYCHANNELS:
		{
			for ( unsigned int i=0; i < AllImgFiles.size(); i++ )
			{
				imgs.push_back ( cvLoadImage ( AllImgFiles[i].c_str (), CV_LOAD_IMAGE_GRAYSCALE ) );
			}

			ssWidth << imgs[0]->width;
			ssWidth >> strWidth;
			ssHeight << imgs[0]->height;
			ssHeight >> strHeight;
			ssNumOfSamples << AllImgFiles.size();
			ssNumOfSamples >> strNumOfSamples;
		}
			break;

		case COLORCHANNELS:
		{
			for ( unsigned int i=0; i < AllImgFiles.size(); i++ )
			{
				cout << "Reading image " << AllImgFiles[i] << endl;				
				imgs.push_back ( cvLoadImage ( AllImgFiles[i].c_str (), CV_LOAD_IMAGE_COLOR ) );
			}
			ssWidth << imgs[0]->width;
			ssWidth >> strWidth;
			ssHeight << imgs[0]->height;
			ssHeight >> strHeight;
			ssNumOfSamples << AllImgFiles.size();
			ssNumOfSamples >> strNumOfSamples;
		}
			break;
	}

	// Track each file in the directory
	vector<string> image_filename_tokens;
	vector<string> last_image_filename_tokens;
	IplImage* outImg;
	CvMat* c;

	for (int i = 0; i < imgs.size(); i++)
	{
		string orig_image_file = AllImgFiles[i].c_str ();
		image_filename_tokens.clear();
		last_image_filename_tokens.clear();
		TokenizeIntoTokensOnly(orig_image_file, image_filename_tokens, ".");
		TokenizeIntoTokensOnly(image_filename_tokens[image_filename_tokens.size()-2], last_image_filename_tokens, "/");

		string asf_file = last_image_filename_tokens[last_image_filename_tokens.size()-1] + ".asf";
		string image_file_opt_output = last_image_filename_tokens[last_image_filename_tokens.size()-1] + "_opt." + image_filename_tokens[image_filename_tokens.size()-1];
		string image_file_init_output = last_image_filename_tokens[last_image_filename_tokens.size()-1] + "_init." + image_filename_tokens[image_filename_tokens.size()-1];
		string image_file_input = last_image_filename_tokens[last_image_filename_tokens.size()-1] + "." + image_filename_tokens[image_filename_tokens.size()-1];

		cout << "Tracking image " << image_file_input << endl; 	

		string target_asf_file = input_dir + "/" + asf_file;
		string target_image_init_file = input_dir + "/" + image_file_init_output;
		string target_image_opt_file = input_dir + "/" + image_file_opt_output;

		if (i == 0)
		{
			// Obtain reference shape
			s = aam_model.GetAAMMeanShape();
			s.CopyShapeParams (aam_model.GetAAMShapes()[0]);

			c = cvCreateMat(aam_model.GetNbOfTruncatedConcatenated(), 1, CV_32FC1);
			cvZero(c);

			cout << "Initialising search on " << image_file_input << endl;
			aam_model.InitializeSearch (imgs[i], s, c);
		}

		outImg = cvCloneImage (imgs[0]);
		aam_model.VO_PutShapeOnTemplateFace(s, imgs[i], outImg);
		cvSaveImage( target_image_init_file.c_str(), outImg);

		// Perform the search
		cout << "Optimising search on " << image_file_input << endl;
		aam_model.OptimizeModel(imgs[i], s, c, 30 );

		outImg = cvCloneImage (imgs[0]);
		aam_model.VO_PutShapeOnTemplateFace(s, imgs[i], outImg);
		cvSaveImage( target_image_opt_file.c_str(), outImg);

		s.WriteASF(target_asf_file, image_file_input, imgs[i]->width, imgs[i]->height);
				
		cvReleaseImage ( &outImg );
	}

	cvReleaseMat( &c);	
	// we're done
	return 0;
}

/**

 @author   Salil Deena
 @version  4-18-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
CAAMConsoleModeG::CAAMConsoleModeG( const string &progname ) {

	m_ProgName  = progname;
	m_NMinParam = 2;
	m_NMaxParam = 3;

	m_Name		= "g";
	m_Usage		= "<model dir> <data file> <recon dir>";
	m_Desc		= "Reconstructs Active Appearance Model movies.";
	m_LongDesc	= string("This mode allows the reconstruction of images from AAM parameters,\n")+
		string("using the AAM model parameter files from <model dir> and data file <data file> specifying the parammeters\n")+
		string("\nOutput are written in <recon dir> if specified or otherwise in current dir.\n\n");
}

/**

 @author   Salil Deena
 @version  4-18-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
int CAAMConsoleModeG::Main(int argc, char **argv) const {
	// call base implementation
	CAAMConsoleMode::Main( argc, argv );

	// setup input parameters	
	string model_dir	= argv[0];		
	string dataFile	= argv[1];
	string recon_directory;

	if (argc > 2)
	{
		recon_directory = argv[2];
	}
	else
	{
		recon_directory = "./";
	}

	string test_model_dir;
	int nChan;

	test_model_dir = model_dir + "/traineddata/RGB/";	

	// Check if the directory specified for the AAM model is valid
	if (boost::filesystem::is_directory(test_model_dir) )
	{
		nChan = COLORCHANNELS;	
	}
	else
	{
		test_model_dir = model_dir + "/traineddata/Gray/";

		if (boost::filesystem::is_directory(test_model_dir) )
		{
			nChan = GRAYCHANNELS;		
		}
		else
		{
			cout << "No AAM model data files are found in the specified directory" << endl;
			exit(1);
		}	
	}

	// Check if the data file is valid
	fstream dataFileRead;
	dataFileRead.open( dataFile.c_str() );

	//check if the data file has been read								
	if(dataFileRead.fail())
	{
		fprintf( stdout, "Failed to open data file\n");
		exit(0);	
	}
	dataFileRead.close();

	VO_AAMBasic aam_model;
	aam_model.VO_Load (test_model_dir);	
	//aam_model.VO_Save (model_dir);

	cout << endl << "Generating frames from data file..." << endl;
	aam_model.VO_ReconstructFromAAMParams (dataFile, recon_directory);

	// we're done
	return 0;	
}

/**

 @author   Salil Deena
 @version  1-11-2010

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
CAAMConsoleModeG2::CAAMConsoleModeG2( const string &progname ) {

	m_ProgName  = progname;
	m_NMinParam = 2;
	m_NMaxParam = 5;

	m_Name		= "g2";
	m_Usage		= "<model dir> <data file> <recon dir> <no_eye_blinks>";
	m_Desc		= "Reconstructs Active Appearance Model movies.";
	m_LongDesc	= string("This mode allows the reconstruction of images from concatenated shape and texture parameters,\n")+
		string("using the AAM model parameter files from <model dir> and data file <data file> specifying the parameters\n")+
		string("\nOutput are written in <recon dir> if specified or otherwise in current dir.\n\n");
}

/**

 @author   Salil Deena
 @version  1-11-2010


 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
int CAAMConsoleModeG2::Main(int argc, char **argv) const {
	// call base implementation
	CAAMConsoleMode::Main( argc, argv );

	// setup input parameters	
	string model_dir	= argv[0];		
	string dataFile	= argv[1];
	string recon_directory;
	string eyes_data_file = "";	
	int no_eye_blinks = 0;

	if (argc > 2)
	{
		recon_directory = argv[2];
		if (argc > 3)
		{
			no_eye_blinks = atoi(argv[3]);	

			if (argc > 4)
			{
				eyes_data_file = argv[4];
			}
		}
	}
	else
	{
		recon_directory = "./";
	}

	string test_model_dir;
	int nChan;

	test_model_dir = model_dir + "/traineddata/RGB/";	

	// Check if the directory specified for the AAM model is valid
	if (boost::filesystem::is_directory(test_model_dir) )
	{
		nChan = COLORCHANNELS;	
	}
	else
	{
		test_model_dir = model_dir + "/traineddata/Gray/";

		if (boost::filesystem::is_directory(test_model_dir) )
		{
			nChan = GRAYCHANNELS;		
		}
		else
		{
			cout << "No AAM model data files are found in the specified directory" << endl;
			exit(1);
		}	
	}

	// Check if the data file is valid
	fstream dataFileRead;
	dataFileRead.open( dataFile.c_str() );

	//check if the data file has been read								
	if(dataFileRead.fail())
	{
		fprintf( stdout, "Failed to open data file\n");
		exit(0);	
	}
	dataFileRead.close();

	// Check datafile for eyes if no_eye_blinks = 3
	if(no_eye_blinks == 3 || no_eye_blinks == 3)
	{
		dataFileRead.open( eyes_data_file.c_str() );

		//check if the data file has been read								
		if(dataFileRead.fail())
		{
			fprintf( stdout, "Failed to open data file\n");
			exit(0);	
		}
		dataFileRead.close();
	}	

	VO_AAMBasic aam_model;

	aam_model.VO_Load (test_model_dir);
	
	//aam_model.VO_Save (model_dir);

	cout << endl << "Generating frames from data file..." << endl;
	aam_model.VO_ReconstructFromConcatenatedParams (dataFile, recon_directory, no_eye_blinks, eyes_data_file);

	// we're done
	return 0;	
}

/**

 @author   Salil Deena
 @version  5-3-2009

 @memo     Debug/Test console mode
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
CAAMConsoleModeD::CAAMConsoleModeD( const string &progname ) {

	m_ProgName  = progname;
	m_NMinParam = 0;
	m_NMaxParam = 100;

	m_Name		= "d";
	m_Usage		= "";
	m_Desc		= "Debug/Test console mode. Don't use!";
	m_LongDesc	= "";
}



/**

 @author   Salil Deena
 @version  4-18-2009

 @memo     Debug function.

 @doc      Debug function.

 @param    
 @param    

 @return   

 */
int CAAMConsoleModeD::Main(int argc, char **argv) const {

	// we're done
	return 0;
}

/**

 @author   Salil Deena
 @version  6-24-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
CAAMConsoleModeT::CAAMConsoleModeT( const string &progname ) {

	m_ProgName  = progname;
	m_NMinParam = 2;
	m_NMaxParam = 2;

	m_Name		= "t";
	m_Usage		= "<model dir> <input movie>";
	m_Desc		= "Performs tracking in a movie file (.avi).";
	m_LongDesc	= string("This mode performs a through initialisation of the AAM in the first frame and\n")+
		string("uses the convergened position as initial pose in the next frame (and so on...).\n\n")+
		string("Example usage:\n\n     " + m_ProgName + " t <model dir> hand.avi\n");
}



/**

 @author   Salil Deena
 @version  6-24-2009

 @memo     
 @doc      
 @see      

 @param    
 @param    

 @return   

 */
int CAAMConsoleModeT::Main(int argc, char **argv) const {

	// we're done
	return 0;
}

/**

 @author   Salil Deena
 @version  7-22-2009

 @memo     

 */
CAAMConsoleModeREG::CAAMConsoleModeREG( const string &progname ) {

	m_ProgName  = progname;
	m_NMinParam = 1;
	m_NMaxParam = 2;

	m_Name		= "reg";
	m_Usage		= "<input dir>";
	m_Desc		= "Registration from a set of shapes.";
	m_LongDesc	= string("This mode creates a registration movie from a set of shapes.\n\n")+				  
		string("input dir          : Directory containing images and annotations.\n")+				  				  
		string("<convex|no-convex*>: Usage of the convex hull as shape extent.\n");
}

/**

 @author   Salil Deena
 @version  7-22-2009

 @memo     

 */
int CAAMConsoleModeREG::Main(int argc, char **argv) const {
	/*
	 // call base implementation
	 CAAMConsoleMode::Main( argc, argv );

	 string asfPath = argv[0];
	 bool useConvexHull = argc>=2 ? 0==strcmp(argv[1],"convex") : false;
	 bool writeRefShape = false;

	 CAAMUtil::RegistrationMovie( "registration.avi", asfPath, useConvexHull, writeRefShape );
	 */

	return 0;
}

